import {
	CustomViewActionType,
	ICustomViewAbility,
	ICustomViewController,
	ICustomViewStore,
	IParam,
	IViewActionResult,
    ICustomViewControllerParams,
    ICustomViewModel,
    IViewEngine,
    IViewEngineParams,
    IDECtrlAbility,
} from '@/core/interface';
import { deepCopy, LogUtil } from '@/core/utils';
import { DEViewController } from './de-view-controller';

/**
 * 自定义视图控制器
 *
 * @export
 * @class CustomViewController
 * @extends {DEViewController<T, S, A>}
 * @implements {ICustomViewController}
 */
export class CustomViewController
	extends DEViewController<
		CustomViewActionType,
		ICustomViewStore,
		ICustomViewAbility
	>
	implements ICustomViewController<ICustomViewStore, ICustomViewAbility>
{

    /**
     * 自定义视图模型
     *
     * @type {ICustomViewModel}
     * @memberof CustomViewController
     */
    declare readonly model: ICustomViewModel;

    /**
     * 部件引擎集合
     *
     * @private
     * @type {IParam[]}
     * @memberof CustomViewController
     */
    private ctrlEngineArray: IParam[] = [];

    /**
     * Creates an instance of CustomViewController.
     * @param {ICustomViewControllerParams<ICustomViewStore, ICustomViewAbility>} params
     * @memberof CustomViewController
     */
    constructor(params: ICustomViewControllerParams<ICustomViewStore, ICustomViewAbility>) {
		super(params);
        this.initCtrlEngineArray();
	}

    /**
     * 初始化引擎集合
     *
     * @private
     * @memberof CustomViewController
     */
    private initCtrlEngineArray() {
		const { engineArray } = this.model;
        this.ctrlEngineArray = [];
        engineArray.forEach((engine: IViewEngine) => {
            const result = this.handleViewEngineParams(engine);
            if (result) {
                this.ctrlEngineArray.push(result);
            }
        })
    }
    
	/**
	 * 视图加载
	 *
	 * @param {IParam} [opts={}]
	 * @memberof CustomViewController
	 */
	public viewMounted(opts: IParam = {}) {
		super.viewMounted(opts);
		if (this.model.useDefaultLayout) {
			if (!this.isLoadDefault) {
				this.isLoadDefault = true;
				return;
			}
			this.load(opts);
		} else {
			this.initLayout().then(() => {
                if (!this.isLoadDefault) {
                    this.isLoadDefault = true;
                    return;
                }
				this.load(opts);
			});
		}
	}

	/**
	 * 视图加载
	 *
	 * @param {IParam} [args]
	 * @return {*}  {Promise<IViewActionResult>}
	 * @memberof CustomViewController
	 */
	public load(args?: IParam): Promise<IViewActionResult> {
        const tempViewParams = deepCopy(this.store.viewParams);
        Object.assign(tempViewParams, args);
        if (this.ctrlEngineArray.length > 0) {
            // 处理搜索部件加载并搜索（参数可指定触发部件）
            for (let engine of this.ctrlEngineArray) {
                if (
                    engine.triggerCtrlName &&
                    Object.is(engine.triggerCtrlName, 'VIEW') &&
                    engine.triggerType &&
                    Object.is(engine.triggerType, 'CtrlLoadAndSearch')
                ) {
                    const ctrl: any = this.getSubAbility<IDECtrlAbility>(engine.targetCtrlName);
                    if (ctrl && ctrl['loadDraft']) {
                        return ctrl['loadDraft'](tempViewParams);
                    }
                }
            }
            // 处理部件加载（参数可指定触发部件）无指定触发部件时由容器触发
            for (let engine of this.ctrlEngineArray) {
                if (
                    engine.triggerType &&
                    Object.is(engine.triggerType, 'CtrlLoad') &&
                    !engine.triggerCtrlName
                ) {
                    const ctrl: any = this.getSubAbility<IDECtrlAbility>(engine.targetCtrlName);
                    if (ctrl) {
                        let action = 'load';
                        if (engine.targetCtrlName && Object.is(engine.targetCtrlName, 'form')) {
                            if (
                                !this.model.entityCodeName ||
                                (this.model.entityCodeName && !this.store.context[this.model.entityCodeName.toLowerCase()])
                            ) {
                                action = 'loadDraft';
                            }
                        }
                        if (ctrl[action]) {
                            return ctrl[action](tempViewParams);
                        }
                    }
                }
            }
        }
		return Promise.reject({
            ok: false,
            data: null,
            rowData: { status: 500 }
        });
	}

	/**
	 * 刷新视图
	 *
	 * @param {(IParam | undefined)} [args]
	 * @return {*}  {Promise<boolean>}
	 * @memberof CustomViewController
	 */
	public async refresh(args?: IParam | undefined): Promise<boolean> {
		return (await this.load(args)).ok
	}

    /**
     * 处理视图引擎参数
     *
     * @private
     * @param {IParam} engine
     * @return {*} 
     * @memberof CustomViewController
     */
    private handleViewEngineParams(engine: IViewEngine) {
        switch (engine.engineType) {
            case 'CtrlLoadTrigger':
                return this.handleCtrlLoad(engine.engineParams);
            case 'CtrlLoad':
                return this.handleCtrlLoad(engine.engineParams);
            case 'CtrlLoadAndSearch':
                return this.CtrlLoadAndSearch(engine.engineParams);
            default:
                LogUtil.warn(`${engine.engineType}暂未支持`);
                break;
        }
    }

    /**
     * 处理搜索部件加载并搜索（参数可指定触发部件）
     *
     * @private
     * @param {IParam} engineParams
     * @return {*} 
     * @memberof CustomViewController
     */
    private CtrlLoadAndSearch(engineParams: IViewEngineParams[]) {
        if (!engineParams || engineParams.length < 1) {
            return null;
        }
        const targetCtrl = engineParams.find((item: any) => {
            return item.name === 'CTRL' && item.paramType === 'CTRL';
        })
        return { triggerCtrlName: 'VIEW', triggerType: 'CtrlLoadAndSearch', targetCtrlName: targetCtrl?.ctrlName };
    }

    /**
     * 处理部件加载（参数可指定触发部件）
     *
     * @private
     * @param {IParam} engineParams
     * @return {*} 
     * @memberof CustomViewController
     */
    private handleCtrlLoad(engineParams: IViewEngineParams[]) {
        if (!engineParams || engineParams.length < 1) {
            return null;
        }
        const triggerCtrl = engineParams.find((item: any) => {
            return item.name === 'TRIGGER' && item.paramType === 'CTRL';
        })
        const targetCtrl = engineParams.find((item: any) => {
            return item.name === 'CTRL' && item.paramType === 'CTRL';
        })
        return { triggerCtrlName: triggerCtrl?.ctrlName, triggerType: 'CtrlLoad', targetCtrlName: targetCtrl?.ctrlName };
    }

    /**
     * 处理部件行为
     *
     * @param {string} name
     * @param {string} action
     * @param {IParam[]} data
     * @memberof CustomViewController
     */
    public handleCtrlAction(name: string, action: string, data: IParam[]): void {
		super.handleCtrlAction(name, action, data);
		if (
            Object.is(action, 'load') ||
            Object.is(action, 'search') ||
            Object.is(action, 'selectionChange') ||
            Object.is(action, 'dataActive') 
        ) {
            for (let engine of this.ctrlEngineArray) {
                if (
                    engine.triggerCtrlName && 
                    Object.is(engine.triggerCtrlName, name) &&
                    engine.triggerType && 
                    Object.is(engine.triggerType, 'CtrlLoad')
                ) {
                    const ctrl: any = this.getSubAbility<IDECtrlAbility>(engine.targetCtrlName);
                    if (ctrl && ctrl['load']) {
                        ctrl['load'](deepCopy(data[0]));
                    }
                }
            }
        }
	}
}
